package com.xc58.highreactor.seril;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import com.xc58.highreactor.annotation.Field;
import com.xc58.highreactor.util.ByteUtil;
import static com.xc58.highreactor.util.ByteUtil.getByteFormInt;

public class DefaultSerializer implements  ISerializer<Object> {
	private static final byte[] ZERO = new byte[]{0,0,0,0};
	private static final StringSerializer SERIALIZER = new StringSerializer(); 
	
	
	public byte[] serialize(Object rawObject) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		String str = rawObject.getClass().getName();
		out.write(getByteFormInt(-1));
		out.write(SERIALIZER.serialize(str));
		
		java.lang.reflect.Field[] fields = rawObject.getClass().getDeclaredFields();
		if(fields != null){
			for (java.lang.reflect.Field field : fields) {
				Field f = field.getAnnotation(Field.class);
				if(f == null){
					continue;
				}
				field.setAccessible(true);
				Object fo = field.get(rawObject);
				if(fo == null){
					out.write(ZERO);
					continue;
				}
				int type = SerialMatcher.getClassFlag(fo.getClass());
				byte[] serial = SerialMatcher.serializer(type, fo);
				if(type != -1){
					out.write(ByteUtil.getByteFormInt(type));
				}
				out.write(serial);
			}
		}
		byte[] result = out.toByteArray();
		return result;
	}

	public Object deserialize(InputStream input) throws Exception {
		String className = SERIALIZER.deserialize(input);
		Class<?> clazz = Class.forName(className);
		
		Object result = clazz.newInstance();
		
		java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
		if(fields != null){
			for (java.lang.reflect.Field field : fields) {
				Field f = field.getAnnotation(Field.class);
				if(f == null){
					continue;
				}
				field.setAccessible(true);
				
				byte[] btype = new byte[4];
				input.read(btype);
				int type = ByteUtil.toInt(btype);
				if(type == 0){
					continue;
				}
				
				field.set(result,SerialMatcher.deserializer(type, input));
			}
		}
		
		
		
		return result;
	}

}
